/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ericsson.nfc.signing.record;

import java.io.UnsupportedEncodingException;
import javax.microedition.contactless.ndef.NDEFRecord;
import javax.microedition.contactless.ndef.NDEFRecordType;

/**
 *
 * @author emarkki
 */
public class URIRecord {

    public static final NDEFRecordType RECORD_TYPE =
            new NDEFRecordType(NDEFRecordType.NFC_FORUM_RTD, "urn:nfc:wkt:U");
    
    private static final String[] abbrevs = new String[]{
        "",
        "http://www.",
        "https://www.",
        "http://",
        "https://",
        "tel:",
        "mailto:",
        "ftp://anonymous:anonymous@",
        "ftp://ftp.",
        "ftps://",
        "sftp://",
        "smb://",
        "nfs://",
        "ftp://",
        "dav://",
        "news:",
        "telnet://",
        "imap:",
        "rtsp://",
        "urn:",
        "pop:",
        "sip:",
        "sips:",
        "tftp:",
        "btspp://",
        "btl2cap://",
        "btgoep://",
        "tcpobex://",
        "irdaobex://",
        "file://",
        "urn:epc:id:",
        "urn:epc:tag:",
        "urn:epc:pat:",
        "urn:epc:raw:",
        "urn:epc:",
        "urn:nfc:",
    };
    
    private byte[] id;
    private String uri;

    public URIRecord(byte[] bytes, int offset) {
        decode(bytes, offset);
    }

    public URIRecord(String uri) {
        this(new byte[0], uri);
    }

    public URIRecord(byte[] id, String uri) {
        this.id = id;
        this.uri = uri;
    }

    public NDEFRecord toNDEFRecord() {
        return new NDEFRecord(RECORD_TYPE, id, encode(uri));
    }

    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (getClass() != obj.getClass()) {
            return false;
        }
        final URIRecord other = (URIRecord) obj;
        if (this.uri != other.uri && (this.uri == null || !this.uri.equals(other.uri))) {
            return false;
        }
        return true;
    }

    public int hashCode() {
        int hash = 3;
        hash = 89 * hash + (this.uri != null ? this.uri.hashCode() : 0);
        return hash;
    }

    public String getURI() {
        return uri;
    }

    public String toString() {
        return "URIRecord[" + uri + "]";
    }

    private void decode(byte[] bytes, int offset) {
        if (bytes.length - offset < 1) {
            throw new IllegalArgumentException("Invalid URI Record, length = " + (bytes.length - offset));
        }

        String suffix = new String(bytes, 1 + offset, bytes.length - 1 - offset);

        if (bytes[offset] == 0x00) {
            uri = suffix;
        } else {
            uri = abbrevs[bytes[offset]] + suffix;
        }
    }

    private static byte[] encode(String uri) {
        try {
            String suffix;
            int abbr = matchingAbbrev(uri);

            if (abbr != 0) {
                suffix = uri.substring(abbrevs[abbr].length());
            } else {
                suffix = uri;
            }

            byte[] bytes = suffix.getBytes("utf-8");
            byte[] ret = new byte[1 + bytes.length];

            ret[0] = (byte) abbr;
            System.arraycopy(bytes, 0, ret, 1, bytes.length);

            return ret;
        } catch (UnsupportedEncodingException ex) {
            throw new IllegalArgumentException("Could not convert. " + ex.getMessage());
        }
    }

    private static int matchingAbbrev(String uri) {
        int match = 0;
        for (int i = 1; i < abbrevs.length; i++) {
            if (uri.startsWith(abbrevs[i]) && abbrevs[i].length() > abbrevs[match].length()) {
                match = i;
            }
        }
        return match;
    }
}
